/* mmuArchLib.h - mmu library header for VxSim */

/* Copyright 1999-2004  Wind River Systems, Inc. */

/*
modification history
--------------------
01e,19aug04,dbt  Removed obsolote mmuArchCurrentSet() prototype.
01d,03dec03,jmp  added mmuArchLibInit().
01c,26nov03,jmp  added mmuArchCurrentSet().
01c,30dec03,kab  Update for VIRT_ADDR type
01b,07oct03,jmp  added MMU_STATE_VALID_NOT.
		 added MMU cache simulation.
01a,17jul03,jmp  imported from VxWorksAE.
*/

#ifndef __INCmmuArchLibh
#define __INCmmuArchLibh

#ifdef __cplusplus
extern "C" {
#endif

#ifdef	HOST
#include "host.h"
#else	/* HOST */
#include "vxWorks.h"
#endif	/* HOST */

/* MMU Page Size */

#ifdef	HOST
#ifndef	WIN32
#define	MMU_PAGE_SIZE	0x2000		/* pages are 8 kbytes */
#else	/* !WIN32 */
#define	MMU_PAGE_SIZE	0x10000		/* pages are 64 kbytes */
#endif	/* WIN32 */

/*
 * VxSim host code does not have access to VIRT_ADDR & PHYS_ADDR, so
 * it is necessary to define them here.
 */

#define VIRT_ADDR	UINT32
#define PHYS_ADDR	UINT32

#else	/* HOST */
#if	CPU != SIMNT
#define	MMU_PAGE_SIZE	0x2000		/* pages are 8 kbytes */
#else	/* CPU != SIMNT */
#define	MMU_PAGE_SIZE	0x10000		/* pages are 64 kbytes */
#endif	/* CPU != SIMNT */
#endif	/* HOST */

/*
 * Page Table Entry (PTE) description:
 *
 *   ______Real Page Number (rpn)_______   ______Page State_______
 *  /                                   \ /                       \
 *  _______________________________________________________________
 * | | | | | | | | | | | | | | | | | | | |U|S|R|W|X| | | | | | |C|V|
 *  ---------------------------------------------------------------
 *                                        | | | | | | | | | | | | |
 *                                        | | | | | | | | | | | | |
 *                        13  User ______/  | | | | | | | | | | | |
 *                        12  Supervisor __/  | | | | | | | | | | |
 *                        11  Read __________/  | | | | | | | | | |
 *                        10  Write ___________/  | | | | | | | | |
 *                         9  Execute ___________/  | | | | | | | |
 *                         8  Reserved ____________/  | | | | | | |
 *                         7  Reserved ______________/  | | | | | |
 *                         6  Reserved ________________/  | | | | |
 *                         5  Reserved __________________/  | | | |
 *                         4  Reserved ____________________/  | | |
 *                         3  Reserved ______________________/  | |
 *                         2  Cache  __________________________/  |
 *                         1  Valid _____________________________/
 *
 * NOTE: On SIMNT, only 16 bits of the rpn bitfield (19 bits) are used.
 *	 This is due to the SIMNT MMU page size.
 */

/* Bit patterns for various MMU states */

#define MMU_STATE_SHIFT			8

#define MMU_STATE_VALID			0x00000001
#define MMU_STATE_VALID_NOT		0x00000000
#define MMU_STATE_CACHEABLE		0x00000002
#define MMU_STATE_CACHEABLE_NOT		0x00000000
#define	MMU_STATE_INVALID_STATE		0xffffffff
#define MMU_STATE_NO_ACCESS		0x00000000

#define MMU_STATE_SUP_RX 		(0x0d << MMU_STATE_SHIFT)
#define MMU_STATE_SUP_RWX 		(0x0f << MMU_STATE_SHIFT)
#define MMU_STATE_USR_SUP_RX 		(0x1d << MMU_STATE_SHIFT)
#define MMU_STATE_USR_RX_SUP_RWX 	(0x15 << MMU_STATE_SHIFT)
#define MMU_STATE_USR_SUP_RWX 		(0x1f << MMU_STATE_SHIFT)


/* Masks associated with the above bit patterns */

#define MMU_STATE_MASK_VALID		0x00000001
#define MMU_STATE_MASK_CACHEABLE	0x00000002
#define MMU_STATE_MASK_PROTECTION	(0x1f << MMU_STATE_SHIFT)

/* Number of L1 and L2 descriptors available in tables */

#if	MMU_PAGE_SIZE == 0x10000 
#define	MMU_NUM_L1_DESC		2048
#define	MMU_NUM_L2_DESC		32
#else	/* MMU_PAGE_SIZE == 0x10000 */
#define	MMU_NUM_L1_DESC		4096
#define	MMU_NUM_L2_DESC		128
#endif	/* MMU_PAGE_SIZE == 0x10000 */

/*
 * Alignment to use to allocate L2 structure. This is necessary to know how
 * much bits are necessary to get the base address of a L2 structure
 * (l2ba field in MMU_LEVEL_2_DESC and MMU_LEVEL_1_DESC structures.
 */

#define	MMU_L2_ALLOC_ALIGNMENT	0x1000

/* Memory size described by a L1 descriptor */

#define MMU_L1_SIZE		(MMU_NUM_L1_DESC * MMU_PAGE_SIZE)

/* Define _BYTE_ORDER macro for host side */

#ifdef	HOST
#if	HOST_BYTE_ORDER == BIG_ENDIAN
#undef	_BIG_ENDIAN
#define	_BIG_ENDIAN	BIG_ENDIAN
#undef	_BYTE_ORDER
#define	_BYTE_ORDER	_BIG_ENDIAN
#else	/* HOST_BYTE_ORDER == BIG_ENDIAN */
#undef	_BIG_ENDIAN
#define	_LITTLE_ENDIAN	LITTLE_ENDIAN
#undef	_BYTE_ORDER
#define	_BYTE_ORDER	_LITTLE_ENDIAN
#endif	/* HOST_BYTE_ORDER == BIG_ENDIAN */
#endif	/* HOST */

/* PTE structure */

typedef union			/* PTE structure			*/
    {
    struct                      /* bit field desciption			*/
        {
#if	_BYTE_ORDER == _BIG_ENDIAN
        UINT32 rpn	:19;	/* real page number			*/
        UINT32 access	:5;	/* Access attributes: USR, SUP, RWX	*/
	UINT32 reserved	:6;	/* Reserved for later use		*/
	UINT32 cache	:1;	/* Cache attribute			*/
	UINT32 v	:1;	/* page valid bit			*/
#else	/* _BYTE_ORDER == _BIG_ENDIAN */
	UINT32 v	:1;	/* page valid bit			*/
	UINT32 cache	:1;	/* Cache attribute			*/
	UINT32 reserved	:6;	/* Reserved for later use		*/
        UINT32 access	:5;	/* Access attributes: USR, SUP, RWX	*/
        UINT32 rpn	:19;	/* real page number			*/
#endif	/* _BYTE_ORDER == _BIG_ENDIAN */
        } field;
    UINT32 bits;
    } PTE;

/* Effective (Virtual) address structure */

typedef union			/* effective address structure		*/
    {
    struct			/* Bit field description		*/
	{
#if	_BYTE_ORDER == _BIG_ENDIAN
#if	MMU_PAGE_SIZE == 0x10000 
	UINT32 l1index	:11;	/* Level 1 Index			*/
	UINT32 l2index	:5;	/* Level 2 Index			*/
	UINT32 po	:16;	/* Page Offset				*/
#else	/* MMU_PAGE_SIZE == 0x10000 */
	UINT32 l1index	:12;	/* Level 1 Index			*/
	UINT32 l2index	:7;	/* Level 2 Index			*/
	UINT32 po	:13;	/* Page Offset				*/
#endif	/* MMU_PAGE_SIZE == 0x10000 */
#else	/* _BYTE_ORDER == _BIG_ENDIAN */
#if	MMU_PAGE_SIZE == 0x10000 
	UINT32 po	:16;	/* Page Offset				*/
	UINT32 l2index	:5;	/* Level 2 Index			*/
	UINT32 l1index	:11;	/* Level 1 Index			*/
#else	/* MMU_PAGE_SIZE == 0x10000 */
	UINT32 po	:13;	/* Page Offset				*/
	UINT32 l2index	:7;	/* Level 2 Index			*/
	UINT32 l1index	:12;	/* Level 1 Index			*/
#endif	/* MMU_PAGE_SIZE == 0x10000 */
#endif	/* _BYTE_ORDER == _BIG_ENDIAN */
	} field;
    VIRT_ADDR effAddr;		/* Note: Requires VIRT_ADDR == UINT32	*/
    } EFFECTIVE_ADDR;

/* Real (Physical) address structure */

typedef union			/* real address structure		*/
    {
    struct			/* Bit field description		*/
	{
#if	_BYTE_ORDER == _BIG_ENDIAN
#if	MMU_PAGE_SIZE == 0x10000 
	UINT32 rpn	:16;	/* Real Page Number			*/
	UINT32 po	:16;	/* Page Offset				*/
#else	/* MMU_PAGE_SIZE == 0x10000 */
	UINT32 rpn	:19;	/* Real Page Number			*/
	UINT32 po	:13;	/* Page Offset				*/
#endif	/* MMU_PAGE_SIZE == 0x10000 */
#else	/* _BYTE_ORDER == _BIG_ENDIAN */
#if	MMU_PAGE_SIZE == 0x10000 
	UINT32 po	:16;	/* Page Offset				*/
	UINT32 rpn	:16;	/* Real Page Number			*/
#else	/* MMU_PAGE_SIZE == 0x10000 */
	UINT32 po	:13;	/* Page Offset				*/
	UINT32 rpn	:19;	/* Real Page Number			*/
#endif	/* MMU_PAGE_SIZE == 0x10000 */
#endif	/* _BYTE_ORDER == _BIG_ENDIAN */
	} field;
    PHYS_ADDR realAddr;		/* Note: Requires PHYS_ADDR == UINT32	*/
    } REAL_ADDR;	

/* Level 2 Descriptor Table structure */

typedef union			/* Level 2 descriptor table structure	*/
    {
    struct			/* Bit field description		*/
    	{
#if	_BYTE_ORDER == _BIG_ENDIAN
	UINT32 l2ba	:20;	/* Level 2 table base address		*/
	UINT32 l2index	:10;	/* Level 2 table Index, note that this	*/
				/* value does not depend on the number	*/
				/* of L2 descriptors. The constraint is */
				/* that l2ba + l2index is 20 and l2ba	*/
				/* is dependent on the allocation	*/
				/* aligment of L2 desc table		*/
	UINT32 reserved	:2;	/* Reserved (must always be zero)	*/
#else	/* _BYTE_ORDER == _BIG_ENDIAN */
	UINT32 reserved	:2;	/* Reserved (must always be zero)	*/
	UINT32 l2index	:10;	/* Level 2 table Index			*/
	UINT32 l2ba	:20;	/* Level 2 table base address		*/
#endif	/* _BYTE_ORDER == _BIG_ENDIAN */
	} field;		
    PTE * pPte;
    } MMU_LEVEL_2_DESC;
    
/* Level 1 Descriptor Table structure */

typedef struct
    {
    UINT32 l2ba		:20;	/* Level 2 table Base Address		*/
    UINT32 v		:1;	/* segment valid bit			*/
    UINT32 pad		:11;	/* padding				*/
    } MMU_LEVEL_1_DESC;

/* MMU translation table structure */

#define	MMU_L1_MASK_SIZE	32

#if	MMU_L1_MASK_SIZE == 8
#define	MMU_L1_MASK_TYPE	UINT8
#elif	MMU_L1_MASK_SIZE == 16
#define	MMU_L1_MASK_TYPE	UINT16
#elif	MMU_L1_MASK_SIZE == 32
#define	MMU_L1_MASK_TYPE	UINT32
#else
#error	"Unsupported MMU_L1_MASK_SIZE value."
#endif

typedef struct mmuTransTblStruct
    {
    MMU_LEVEL_1_DESC *	pLvl1Tbl;	/* Level1 descriptor table	*/
    UINT32		firstL1Ix;	/* First L1 index used		*/
    UINT32		lastL1Ix;	/* Last L1 index used		*/
    MMU_L1_MASK_TYPE	l1Mask[MMU_NUM_L1_DESC/MMU_L1_MASK_SIZE];
    } MMU_TRANS_TBL;

#ifndef HOST
extern	STATUS	mmuArchLibInit		(UINT pageSize);
#endif	/* HOST */

#ifdef __cplusplus
}
#endif

#endif /* __INCmmuArchLibh */
